﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace Nature.Data.CkMarkup
{
    using Nature.Text;

    /// <summary>
    /// Chemkin text source 
    /// </summary>
    [Serializable]
    public partial class CkTextSource : TextSource
    {
        #region Static Members

        public static readonly string PatternRealNumber;
        public static readonly string PatternSignedRealNumber;
        public static readonly string PatternSpeciesCodeBase;
        public static readonly string PatternEnergyUnitsBase;
        public static readonly string PatternAmountUnitsBase;
        public static readonly string PatternUnitsItem;

        public static readonly Regex RegexRealNumber;
        public static readonly Regex RegexSignedRealNumber;
        public static readonly Regex RegexValidSpeciesCode;
        public static readonly Regex RegexUnitsItem;

        static CkTextSource()
        {
            string realNumber = NormalizePattern(
                @"
                    (?:                    
                        (?: 
                            (?:\d+\.?\d*) | (?:\.\d+) 
                        )                            
                        (?:[edf][+-]?\d{1,3})?               
                    )
                ");
            string signedRealNumber = NormalizePattern(string.Format("(?:[+-]?(?:{0}))", realNumber));
            string prnSpeciesCodeBase = NormalizePattern(
                    @"
                        (?:
                            (?!\b(?:m|hv)\b)
                            (?:                       
                                (?: [(] [^\s()]* [)]  | (?:\w[-,])+\w | \w )+
                                \+*
                            )
                        )
                    "
                );

            string patternEnergyUnitsBase = NormalizePattern(
                @"(?:
                    (?:k(?:ilo)?)?
                    (?:
                        joul(?:es?)? | cal(?:ories?)? | ergs? | evolts?   
                    )                  
                )");
            string patternAmountUnitsBase = NormalizePattern(
                @"
                    (?:
                        (?:   (?:k(?:ilo)?)?  mol(?:es?)?    ) | 
                        molec(?:ules?)?
                    )
                ");

            string prnUnitsItem = NormalizePattern(
                @"
                     (?: (?=\S)
                        (?<activationEnergy> (?<energy>@energy) \s* [%/] \s* (?<amount>@amount) \b) | 
                        (?<energy> \b @energy \b ) | 
                        (?<amount> \b @amount \b ) | 
                        (?<activationEnergy> (?<temperature>kelv(?:ins?)?|celcius|fahrenheits?) )|
                        (?<defect> \S+ ) 
                     )
                ".Replace("@energy", patternEnergyUnitsBase)
                 .Replace("@amount", patternAmountUnitsBase)
                 );

            string prnValidSpeciesCode = NormalizePattern(
                    string.Format("^{0}$", prnSpeciesCodeBase)
                );


            PatternEnergyUnitsBase = patternEnergyUnitsBase;
            PatternAmountUnitsBase = patternAmountUnitsBase;
            PatternUnitsItem = prnUnitsItem;

            realNumber = Regex.Replace(realNumber, @"\s+", string.Empty);
            signedRealNumber = Regex.Replace(signedRealNumber, @"\s+", string.Empty);
            PatternRealNumber = realNumber;
            PatternSignedRealNumber = signedRealNumber;
            PatternSpeciesCodeBase = prnSpeciesCodeBase;
            RegexRealNumber = new Regex(realNumber, RegexOptions.Compiled);
            RegexSignedRealNumber = new Regex(signedRealNumber, RegexOptions.Compiled);
            RegexValidSpeciesCode = new Regex(prnValidSpeciesCode, RegexOptions.Compiled);
            RegexUnitsItem = new Regex(prnUnitsItem, RegexOptions.Multiline | RegexOptions.Compiled);

        }
        #endregion

        protected override string CreateAdaptedVersion()
        {
            string text = OriginalText;
            Regex rgx = new Regex(
                @"
                    (?<literal>"" [^""]* "") | 
                    (?<comment> [!] [^\r\n]* ) |
                    (?: [^""!]+)
                ", RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline);
            text = rgx.Replace(text, m =>
            {
                if (m.Groups["literal"].Success) { return m.Value; }
                if (m.Groups["comment"].Success) { return new string(' ', m.Length); }
                return m.Value.ToLower();
            });

            rgx = new Regex(@"[&] (?: [^\S\r\n]* [\r\n] )+ ", RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline);
            text = rgx.Replace(text, m => new string(' ', m.Length));
            text = Regex.Replace(text, "\t+", m => new string(' ', m.Length));
            return text;
        }

    }
}
